home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload Trio 2
/
Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO
/
dir34
/
2m21src.zip
/
2MF.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-05-31
|
33KB
|
939 lines
/*───────────────────────────────────────────────────────────────────\
│ │
│ █████ █ █ █▀▀▀▀ │
│ █ ██ ██ █ │
│ █████ █ █ █ █▀▀ │
│ █ █ █ █ │
│ █████ █ █ █ │
│ │
│ 2MF.C 2.1 - UTILIDAD DE FORMATEO DE DISQUETES 2M │
│ │
│ (c) 1994 Ciriaco García de Celis. │
│ │
│ - Para Borland C++ 2.0 ó superior en modelo de memoria LARGE. │
│ - Este programa se compila abriendo un proyecto e introduciendo │
│ en él 2MF.C, 2MFKIT.OBJ, 2MFBOTHD.OBJ y 2MFBOTDD.OBJ │
│ │
│ - NOTA: Las funciones de bajo nivel que acceden directamente a │
│ la controladora de disquetes no son indispensables, tan │
│ sólo se emplean para producir menos ruido al detectar │
│ la introducción de un nuevo disquete en la unidad. │
│ │
\───────────────────────────────────────────────────────────────────*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dos.h>
#include <bios.h>
#include <time.h>
#include <alloc.h>
unsigned _stklen=16384;
#define MAXSECT 46 /* máximo número de sectores por pista */
#define MAXFAT 6128 /* mayor FAT de 12 bits posible */
#define FD_DATA 0x3F5 /* registro de datos del 765 */
#define FD_STATUS 0x3F4 /* registro principal de estado del 765 */
#define FD_DOR 0x3F2 /* registro de salida digital */
#define FD_DIR 0x3F7 /* registro de entrada digital (RD) */
#define FD_DCR 0x3F7 /* registro de control del disquete (WR) */
struct boot { /* sector arranque disquetes 2M */
unsigned char Salto[3], IdSis[8];
short BytesSect;
char SectCluster;
short SectReserv;
char NumFats;
short FichRaiz, NumSect;
char MediaId;
short SectFat, SectPista, Caras;
long Especiales, Sect32;
char Unidad, Reservado, Flag;
long NumSerie;
char Titulo[11], TipoFat[8];
char NoUsado;
char CheckSum;
char VersionFmt, FlagWr, VelPista0, VelPistaX;
short OffsetJmp, OffsetPista0, OffsetPistaX, OffsetListaTam;
char Resto[512-76];
};
struct parametros { /* parámetros en línea de comandos */
int Unidad, HD, ED, TipoFmt, NoVerify, MarcaPoco,
Pistas, FichRaiz, Silencioso, NoPausa, X, Y, G;
};
int HablaSp(), Hay2m(), Hay2mBoot(), FormatearDisco(), MarcaFat(),
TipoDrive(), InicializaDisco(), EsperarCambioDisco(), infdc();
void Ayuda(), ProcesarParametros(), CrearSector0(),
DiagnosticoError(), InformeError(), InformeDisco(),
SonidoSube(), SonidoBaja(), SonidoError(), SonidoOn(),
SonidoOff(), Sonido(), posicionar(), outfdc(), EsperarInt();
extern BootHDPrg, BootHDPrgLong, BootDDPrg, BootDDPrgLong,
Boot2mCode, Boot2mLong, biosdsk();
extern void PicoRetardo();
int sp; /* 1-español 0-inglés */
unsigned char far *fat; /* para contener toda la FAT */
unsigned char far *buffer; /* para contener toda una pista */
unsigned long far *cbios=MK_FP(0x40, 0x6C); /* reloj del sistema */
unsigned char far *irq6=MK_FP(0x40, 0x3E); /* flag BIOS de IRQ6 */
void main (int argc, char **argv)
{
struct boot sector0;
struct parametros cmd;
int salir, result, sg;
long bytes_err, dir;
sp=HablaSp(); /* determinar idioma del país */
ProcesarParametros (argc, argv, &cmd);
if (!Hay2m())
if (!Hay2mBoot()) {
if (sp)
printf(" 2M ó 2MX 2.1 no está instalado, imposible formatear.\n");
else
printf(" 2M or 2MX 2.1 is not installed, impossible to format.\n");
exit(128);
}
else {
if (sp)
printf(" Modo SuperBOOT: instale 2M para dar formato.\n");
else
printf(" SuperBOOT mode: needed to install 2M to format.\n");
exit(127);
}
if (((fat=farmalloc( (unsigned long) MAXFAT))==NULL) ||
((buffer=farmalloc( (unsigned long) MAXSECT<<10))==NULL)) {
if (sp) printf(" Memoria insuficiente.\n");
else printf(" Insufficient memory.\n");
exit(126);
}
/* Definir el buffer para que no cruce una frontera de DMA */
dir = ((unsigned long) FP_SEG(buffer) <<4) + FP_OFF(buffer);
if ((dir >> 16) != ((dir + ((unsigned long) MAXSECT << 9)) >> 16))
buffer+=(unsigned long) MAXSECT << 9;
if (!cmd.NoPausa) {
if (sp)
printf(" Pulsa una tecla para formatear en");
else
printf(" Press any key to format on");
printf(" %c:", cmd.Unidad+'A');
salir=getch()==27;
}
else
salir=0;
while (!salir) {
CrearSector0 (§or0, cmd);
if (!cmd.Silencioso) SonidoSube();
switch (result=FormatearDisco (§or0, &cmd, &bytes_err, &sg)) {
case 0: InformeDisco (§or0, bytes_err, sg);
if (!cmd.Silencioso) SonidoBaja(); break;
case 1: DiagnosticoError (result);
break;
default: DiagnosticoError (result);
if (!cmd.Silencioso) SonidoError(); break;
}
if (sp)
printf("\n Introduce otro disquete para formatear en");
else
printf("\n Please insert another disk to format in");
printf(" %c:", cmd.Unidad+'A');
if (!EsperarCambioDisco(cmd.Unidad)) salir=1;
}
printf("\r \r");
}
void ProcesarParametros(int argc, char **argv, struct parametros *cmd)
{
int pm, error=0, hlp=0, id=1;
cmd->Unidad=cmd->TipoFmt=cmd->ED=cmd->NoVerify=cmd->MarcaPoco=0;
cmd->HD=1; cmd->Pistas=82;
cmd->FichRaiz=cmd->Silencioso=cmd->NoPausa=0;
cmd->X=cmd->Y=cmd->G=-1;
for (pm=1; pm<argc; pm++) {
strupr (argv[pm]);
if (strstr(argv[pm],"/?")!=NULL) hlp++;
else if (strstr(argv[pm],"/H")!=NULL) hlp++;
else if ((strstr(argv[pm],"A:")!=NULL) ||
(strstr(argv[pm],"B:")!=NULL)) cmd->Unidad=*argv[pm]-'A';
else if (strstr(argv[pm],"/DD")!=NULL) cmd->HD=0;
else if (strstr(argv[pm],"/D0")!=NULL) cmd->HD=2;
else if (strstr(argv[pm],"/D1")!=NULL) cmd->HD=3;
else if (strstr(argv[pm],"/F")!=NULL) cmd->TipoFmt=0;
else if (strstr(argv[pm],"/M")!=NULL) cmd->TipoFmt=1;
else if (strstr(argv[pm],"/E")!=NULL) cmd->ED=1;
else if (strstr(argv[pm],"/N")!=NULL) cmd->NoVerify=1;
else if (strstr(argv[pm],"/W")!=NULL) cmd->MarcaPoco=1;
else if (strstr(argv[pm],"/T")!=NULL)
cmd->Pistas = atoi (&argv[pm][3]);
else if (strstr(argv[pm],"/R")!=NULL)
cmd->FichRaiz = atoi (&argv[pm][3]);
else if (strstr(argv[pm],"/S")!=NULL) { cmd->Silencioso=1; id++; }
else if (strstr(argv[pm],"/K")!=NULL) cmd->NoPausa=1;
else if (strstr(argv[pm],"/X")!=NULL) cmd->X=atoi(&argv[pm][3]);
else if (strstr(argv[pm],"/Y")!=NULL) cmd->Y=atoi(&argv[pm][3]);
else if (strstr(argv[pm],"/G")!=NULL) cmd->G=atoi(&argv[pm][3]);
else if (strstr(argv[pm],"/I")!=NULL) { sp^=1; id++; }
else error=1;
}
if (cmd->ED && (cmd->HD!=1)) cmd->HD=1; /* /DD ó /Dx + /E = /E */
if ((argc<=1) || (argc==id)) hlp++;
if (hlp) Ayuda();
if (sp)
printf("\n2MF 2.1 - Utilidad de formateo de disquetes 2M (ESC Salir)\n");
else
printf("\n2MF 2.1 - Format utility program for 2M diskettes (ESC Aborts)\n");
if (error) {
if (sp)
printf(" Error de sintaxis. Ejecute 2MF /?.\n");
else
printf(" Incorrect parameter(s). Execute 2MF /?.\n");
exit (2);
}
if (TipoDrive(cmd->Unidad)==0) {
if (sp)
printf(" La unidad física indicada no existe.\n");
else
printf(" Physical drive indicated does not exist.\n");
exit (2);
}
if ((TipoDrive(cmd->Unidad)!=2) && (TipoDrive(cmd->Unidad)<4)) {
if (sp)
printf(" La unidad indicada no es de alta densidad.\n");
else
printf(" Drive indicated it is not high density one.\n");
exit (2);
}
if ((TipoDrive(cmd->Unidad)<5) && (cmd->ED==1)) {
if (sp)
printf(" Necesaria unidad de 2.88M para formato ED.\n");
else
printf(" Needs a 2.88M drive to perform ED format.\n");
exit (2);
}
if ((cmd->Pistas<80) || (cmd->Pistas>86)) {
if (sp)
printf(" Error: Número de pistas incorrecto.\n");
else
printf(" Error: Incorrect number of tracks.\n");
exit (2);
}
if (cmd->FichRaiz && ((cmd->FichRaiz<1) || (cmd->FichRaiz>240))) {
if (sp)
printf(" Error: Nº de ficheros en directorio raiz erróneo.\n");
else
printf(" Error: Bad number of files in root directory.\n");
exit (2);
}
}
void Ayuda(void)
{
if (sp) {
printf("\n\n"
" 2MF 2.1 - UTILIDAD ESTANDAR DE FORMATEO DE DISQUETES PARA 2M\n"
" (c) 1994 Ciriaco García de Celis - Grupo Universitario de Informática\n"
" C/Renedo, 2, 4-C; 47005 Valladolid (España) - ciri@gui.uva.es - 2:341/21.8\n\n"
" 2MF U: [/DD] [/F|M] [/E] [/N] [/T=nn] [/R=nn] [/S] [/K]\n\n"
" Este programa formatea disquetes a una mayor capacidad y/o velocidad de la\n"
" normal. Para que estos nuevos disquetes funcionen debe estar instalado 2M en\n"
" memoria. Alternativamente, si son de alta densidad se pueden dejar dentro de\n"
" la unidad A: y reinicializar el ordenador, que botará pese a todo del disco\n"
" duro y podrá acceder a los disquetes 2M sin problemas en lectura y escritura\n"
" normales. Este programa es gratuíto y de tipo «CARDWARE». Opciones:\n\n"
" /DD Solicita un formateo en doble densidad -por defecto se hace en alta-.\n"
" /F Disquetes rápidos y seguros -por defecto- (5¼:820-1476K, 3½:984-1804K).\n"
" /M Formatear disquetes a la máxima capacidad (5¼:902-1558K, 3½:1066-1886K).\n"
" /E Formatear disquetes de 3½-ED (3608K por defecto o 3772K indicando /M).\n"
" /N No verificar el disquete destino (peligroso en modo /M).\n\n"
" /T Modificar el número de pistas por defecto (80-86).\n"
" /R Modificar el número de ficheros permitidos en directorio raíz (1-240).\n"
" /S Funcionamiento silencioso sin emitir sonido.\n"
" /K No realizar pausa inicial antes de comenzar.\n");
}
else {
printf("\n\n"
" 2MF 2.1 - STANDARD FORMAT UTILITY FOR 2M DISKETTES\n"
" (c) 1994 Ciriaco García de Celis - Grupo Universitario de Informática\n"
" C/Renedo, 2, 4-C; 47005 Valladolid (Spain) - ciri@gui.uva.es - 2:341/21.8\n\n"
" 2MF U: [/DD] [/F|M] [/E] [/N] [/T=nn] [/R=nn] [/S] [/K]\n\n"
" This program formats diskettes at a higher capacity and/or speed than the\n"
" normal ones. 2M must be installed on memory to provide support for the new\n"
" diskettes. Also, high-density diskettes can be left into A: drive and then\n"
" computer can be rebooted: really it will boot from hard disk and after this\n"
" moment 2M diskettes will be supported in the standard read-write operation.\n"
" 2MF is a 100%% CARDWARE utility. Meaning of switches:\n\n"
" /DD Request a double-density format (by default it will be high-density).\n"
" /F Fast and secure diskettes -by default- (5¼:820-1476K, 3½:984-1804K).\n"
" /M Formats diskettes up to maximum capacity (5¼:902-1558K, 3½:1066-1886K).\n"
" /E Formats 3.5-ED diskettes at 3608K (or 3772K if /M option enabled).\n"
" /N Do not verify target diskette (dangerous in /M mode).\n\n"
" /T Sets the number of tracks to be used (80-86).\n"
" /R Sets the number of root directory entries (1-240).\n"
" /S Tells 2MF not to make sound effects.\n"
" /K No initial pause before formatting.\n");
}
exit (1);
}
int Hay2m() /* devolver 1 si 2M está instalado */
{
int entrada, instalado=0;
union REGS r; struct SREGS s;
for (entrada=0xc0; (entrada<=0xff) && (!instalado); entrada++) {
r.x.ax=entrada << 8; s.es=0x1492; r.x.di=0x1992;
int86x (0x2f, &r, &r, &s);
if (r.x.ax==0xFFFF)
if ((peek(s.es,r.x.di-4)==9002) && (peek(s.es,r.x.di-2)==10787))
if (strstr (MK_FP(s.es, r.x.di),"2M:2.1")) instalado=1;
if (strstr (MK_FP(s.es, r.x.di),"2MX:2.1")) instalado=1;
}
return (instalado);
}
int Hay2mBoot() /* devolver 1 si 2M instalado en modo SuperBOOT */
{
return (strstr(MK_FP(((unsigned) peek(0x40, 0x13) * 64), 4),
"2M-STV")!=NULL);
}
void CrearSector0 (struct boot *s0, struct parametros cmd)
{
unsigned tipo, tabla, i, j, k, m, t, s, tam, ini, fin, inc;
char id[8]="2M-STV00", ch, sum, far *p;
static unsigned char infofis [2][3][2][4][20] =
{{{{{10,176,7,0,1,1}, {9,80,1,1}, /* 5¼-DD /F */
{5,100,3,1,1} },
{{11,176,7,1,1,1}, {9,80,1,1}, /* /M */
{32,4,5,3,1,4,2,0}, {4,2,4,3,0} }},
{{{18,224,7,0,0,0}, {16,60,1,1}, /* 5¼-HD /F */
{9,50,3,1,2} },
{{19,224,7,1,0,0}, {17,25,1,2}, /* /M */
{53,3,6,4,1,5,2,6,3}, {4,4,2,4,4,3} }},
{{{0,0,0,0,0,0}, {0,0,0,0}, /* no usado */
{0,0,0,0,0}, },
{{14,192,7,1,2,1}, {9,80,1,1}, /* 3½-DD /D1 */
{38,2,4,3,1,4,2}, {4,3,4,4} }}},
{{{{12,192,7,0,2,1}, {9,80,1,1}, /* 3½-DD /F */
{6,100,3,1,1} },
{{13,192,7,1,2,1}, {9,80,1,1}, /* /M */
{38,5,6,3,1,4,2,0,0}, {4,2,4,4,0,0} }},
{{{22,224,7,0,0,0}, {19,70,1,1}, /* 3½-HD /F */
{11,40,3,1,2} },
{{23,224,7,1,0,0}, {19,70,1,1}, /* /M */
{64,3,7,4,1,5,2,6,3,7}, {4,4,4,4,4,3,2} }},
{{{44,240,7,0,3,3}, {36,108,1,1}, /* 3½-ED /F */
{11,126,4,1,2} },
{{46,240,7,1,3,3}, {36,108,1,1}, /* /M */
{127,5,12,1,7,2,8,3,9,4,10,5,11,6,12},
{4,4,4,4,4,4,4,4,4,4,4,3} }}}};
/* Significado de la tabla /F:
{SectLogPistaX, fichraiz, verFmt, flagWr, velpista0, velpistaX},
{sectpista0, GAP3pista0, primsectpista0, interleavepista0},
{SectFisPistaX, GAP3pistaX, tamsectpistaX, /X, /Y}
Significado de la tabla /M:
{SectLogPistaX, fichraiz, verFmt, flagWr, velpista0, velpistaX},
{sectpista0, GAP3pista0, primsectpista0, interleavepista0},
{Sectpreformat, GAP3pistaX, SectFisPistaX, sects numerados...},
{tamaños de sectores por orden...}
*/
if ((cmd.HD==2) && (TipoDrive(cmd.Unidad)>=4)) {
cmd.HD=0; tabla=0; tipo=0;
infofis[0][0][cmd.TipoFmt][0][4]=2; /* 3½-DD a 250 Kbps */
infofis[0][0][cmd.TipoFmt][0][5]=2;
}
else if ((cmd.HD==3) && (TipoDrive(cmd.Unidad)>=4)) {
cmd.HD=tipo=0;
cmd.TipoFmt=1; tabla=2; /* 3½-DD con 1148K */
}
else {
if (cmd.HD>1) cmd.HD=0;
tabla=cmd.HD+cmd.ED; /* seleccionar tabla de datos */
if (TipoDrive(cmd.Unidad)<3)
tipo=0; /* 5¼ */
else
tipo=1; /* 3½ */
}
s0->NoUsado=0;
ch=1+cmd.HD;
if (TipoDrive(cmd.Unidad)>2) ch+=2; if (!cmd.TipoFmt) ch+=4;
if (cmd.ED) ch=10-cmd.TipoFmt;
id[6]=(ch/10)+'0'; id[7]=(ch % 10)+'0'; strncpy (s0->IdSis, id, 8);
s0->BytesSect=512;
s0->SectCluster = s0->SectReserv = 1; s0->NumFats=2;
if (cmd.ED) s0->SectCluster=2;
if (!cmd.FichRaiz)
s0->FichRaiz=infofis[tipo][tabla][cmd.TipoFmt][0][1];
else
if (cmd.FichRaiz % 16)
s0->FichRaiz=((cmd.FichRaiz >> 4) + 1) << 4;
else
s0->FichRaiz=cmd.FichRaiz;
if (ch==6)
s0->MediaId=0xF0; /* compatible SCANDISK */
else
s0->MediaId=0xFA; /* compatible SCANDISK */
s0->SectPista=infofis[tipo][tabla][cmd.TipoFmt][0][0];
s0->Caras=2;
s0->NumSect=cmd.Pistas*s0->Caras*s0->SectPista;
j = 3 * (s0->NumSect - (s0->FichRaiz>>4) - 1);
k = 6 + 1024 * s0->SectCluster;
s0->SectFat = j/k; if (j % k) s0->SectFat++;
s0->Unidad = s0->Reservado = 0; s0->Especiales = s0->Sect32 = 0L;
s0->Flag=0x29; randomize();
for (i=0; i<4; i++)
s0->NumSerie = (s0->NumSerie<<8) | (unsigned char) random(32767);
strncpy (s0->Titulo, "NO NAME ", 11);
strncpy (s0->TipoFat, "FAT12 ", 8);
s0->VersionFmt=infofis[tipo][tabla][cmd.TipoFmt][0][2];
s0->FlagWr=infofis[tipo][tabla][cmd.TipoFmt][0][3];
s0->VelPista0=infofis[tipo][tabla][cmd.TipoFmt][0][4];
s0->VelPistaX=infofis[tipo][tabla][cmd.TipoFmt][0][5];
tam=76; /* lo que precede a la primera tabla */
s0->OffsetPista0=tam;
s0->Resto[0]=infofis[tipo][tabla][cmd.TipoFmt][1][0];
s0->Resto[1]=infofis[tipo][tabla][cmd.TipoFmt][1][1];
ch=infofis[tipo][tabla][cmd.TipoFmt][1][2];
inc=infofis[tipo][tabla][cmd.TipoFmt][1][3];
ini=tam+2; fin=ini+s0->Resto[0]; k=0;
for (i=j=0; j<s0->Resto[0]; j++) {
s0->Salto[ini+i]=ch++; if (ch>s0->Resto[0]) ch=1;
i+=inc; if (ini+i>=fin) i=++k;
}
ini=fin; s0->OffsetPistaX=ini;
if (!s0->FlagWr) {
k=infofis[tipo][tabla][cmd.TipoFmt][2][0]; j=5;
for (i=0; i<j; i++)
s0->Salto[ini+i]=infofis[tipo][tabla][cmd.TipoFmt][2][i];
if (cmd.X!=-1) s0->Salto[ini+3]=cmd.X;
if (cmd.Y!=-1) s0->Salto[ini+4]=cmd.Y;
}
else {
k=infofis[tipo][tabla][cmd.TipoFmt][2][2]; j=(k+1)*3;
for (i=0; i<3; i++)
s0->Salto[ini+i]=infofis[tipo][tabla][cmd.TipoFmt][2][i];
m=129;
for (i=3; i<=k*3; i+=3) {
s0->Salto[ini+i]=m;
s=infofis[tipo][tabla][cmd.TipoFmt][2][i/3+2];
s0->Salto[ini+i+1]=s;
t=infofis[tipo][tabla][cmd.TipoFmt][3][s-1];
switch (t) {
case 0: m+=1; break; case 1: m+=2; break;
case 2: m+=3; break; case 3: m+=6; break;
case 4: m+=11; break; case 5: m+=22; break;
}
s0->Salto[ini+i+2]=t;
}
}
if (cmd.G!=-1) s0->Salto[ini+1]=cmd.G;
fin=ini+j;
ini=fin; s0->OffsetListaTam=ini;
if (!s0->FlagWr)
for (i=0; i<k; i++)
s0->Salto[ini+i]=infofis[tipo][tabla][cmd.TipoFmt][2][2];
else
for (i=0; i<k; i++)
s0->Salto[ini+i]=infofis[tipo][tabla][cmd.TipoFmt][3][i];
fin=ini+k;
ini=fin; s0->OffsetJmp=ini;
s0->Salto[0]=0xE9;
s0->Salto[1]=(ini-3) % 256; s0->Salto[2]=(ini-3) >> 8;
if (cmd.HD == 0) {
p=(char far *) &BootDDPrg; k=BootDDPrgLong; }
else {
p=(char far *) &BootHDPrg; k=BootHDPrgLong; }
for (i=0; (i<k) && (ini+i<509); i++) s0->Salto[ini+i]=*p++;
fin=ini+i;
for (i=fin; i<510; i++) s0->Salto[i]=0;
if (fin<497) strncpy (&s0->Salto[496], "Made in Spain", 13);
s0->Salto[509]=0; s0->Salto[510]=0x55; s0->Salto[511]=0xAA;
for (sum=0, j=64; j<ini; j++) sum+=s0->Salto[j]; /* checksum */
s0->CheckSum=-sum;
}
int FormatearDisco (sector0, cmd, bytes_defectuosos, segundos)
struct boot *sector0;
struct parametros *cmd;
long *bytes_defectuosos;
int *segundos;
{
unsigned long dir, tiempo, rest, tini, hist[86], i;
int cilindros, cilindro, cabezal, intento, error=1, spista, t;
unsigned long fase, fases;
if (cmd->G!=-1)
if (sp)
printf("\r AVISO: ¡Valor de GAP alterado con opción /G!\n");
else
printf("\r WARNING: GAP value modified with /G switch!\n");
if (cmd->HD>1)
if (sp)
printf("\r AVISO: ¡Parámetro indocumentado /D%d activo!\n",
cmd->HD-2);
else
printf("\r WARNING: Undocumented /D%d switch activated!\n",
cmd->HD-2);
if (cmd->MarcaPoco)
if (sp)
printf("\r AVISO: ¡Parámetro indocumentado /W activo!\n");
else
printf("\r WARNING: Undocumented /W switch activated!\n");
if ((cmd->X!=-1) || (cmd->Y!=-1))
if (sp)
printf("\r AVISO: ¡Parámetro indocumentado /X ó /Y activo!\n");
else
printf("\r WARNING: Undocumented /X or /Y switch activated!\n");
if (sp)
printf("\r Formateo de disquete ");
else
printf("\r Formatting ");
switch (TipoDrive (cmd->Unidad)) {
case 2: printf("%s", cmd->HD==1?"5¼-1.2M":"5¼-360K"); break;
case 4: printf("%s", cmd->HD==1?"3½-1.44M":"3½-720K"); break;
default: if (cmd->ED) printf("3½-2.88M");
else printf("%s", cmd->HD==1?"3½-1.44M":"3½-720K");
}
if (sp)
printf(" en %c: con %dK \n",
cmd->Unidad+'A', sector0->NumSect>>1);
else
printf(" diskette on %c: with %dK \n",
cmd->Unidad+'A', sector0->NumSect>>1);
for (i=0; i<MAXFAT; i++) fat[i]=0; /* poner a 0 la futura FAT */
fat[0]=sector0->MediaId; fat[1]=fat[2]=0xFF;
for (i=0; i < ((unsigned long) MAXSECT <<9); i++) buffer[i]=0;
cilindros=sector0->NumSect/(sector0->SectPista*sector0->Caras);
spista=sector0->SectPista; *bytes_defectuosos=0L;
fases=1L*cilindros*sector0->Caras*(1+(1-cmd->NoVerify)+sector0->FlagWr);
fase=0L;
tini=*cbios;
for (cilindro=0; cilindro < cilindros; cilindro++) {
for (cabezal=0; cabezal<sector0->Caras; cabezal++) {
for (intento=0; intento<3; intento++) {
if (sp)
printf("\r Cilindro %2d - Cara %d [F-] %3lu%%",
cilindro, cabezal, fase*100/fases);
else
printf("\r Cylinder %2d - Side %d [F-] %3lu%%",
cilindro, cabezal, fase*100/fases);
if (error) biosdsk (0, cmd->Unidad);
t=0; while (bioskey(1)) t=bioskey(0);
if ((t & 0xFF)==0x1B) { error=1; goto AbortFormat; }
else if ((t==0x1000) && (cilindro>1)) goto FinFormat;
error=biosdsk (5, cmd->Unidad, cabezal,
cilindro, 0, 0x7F, sector0);
if (sector0->FlagWr==1) if (!error && (cilindro | cabezal)) {
printf ("\b\b\b\b\b\b\b\b\bI-] %3lu%%",(fase+1)*100/fases);
error=biosdsk (3, cmd->Unidad, cabezal | 0x80,
cilindro, 1, spista, buffer);
}
if (!error&&(!cmd->NoVerify||(cmd->NoVerify && cilindro<2))) {
printf ("\b\b\b\b\b\b\b\b\b-V] %3lu%%",
(fase+1+sector0->FlagWr)*100/fases);
error=biosdsk (2, cmd->Unidad, cabezal,
cilindro, 1, spista, buffer);
}
if (!error) break;
}
if (error)
if ((error==128) || (error==3) || (error==6))
goto AbortFormat; /* error fatal */
else
if (!MarcaFat(cmd->Unidad, cmd->MarcaPoco, sector0,
cilindro, cabezal, fat, bytes_defectuosos))
goto AbortFormat; /* error en áreas del sistema */
fase+=(1+(1-cmd->NoVerify)+sector0->FlagWr);
}
hist[cilindro]=*cbios;
tiempo=(*cbios-tini)*10/182;
printf(" [%2lu:%02lu ]", tiempo/60, tiempo % 60);
if (cilindro>5) {
rest=(*cbios-hist[cilindro-5])*(cilindros-cilindro)*10/910;
printf("\b+%2lu:%02lu =%2lu:%02lu ]", rest/60, rest % 60,
(tiempo+rest)/60, (tiempo+rest) % 60);
}
}
FinFormat: error=InicializaDisco (cmd->Unidad, sector0, fat);
AbortFormat: printf("\r"); for (i=0; i<79; i++) printf(" ");
*segundos=(*cbios-tini)*10/182;
return (error);
}
void InformeDisco (struct boot *s0, long bd, int tiempo)
{
unsigned long st, ua, bt;
st = s0->NumSect - s0->NumFats * s0->SectFat
- s0->SectReserv - (s0->FichRaiz>>4);
ua = st / (unsigned long) s0->SectCluster; bt = st*512L;
if (sp) {
printf ("\r Tiempo transcurrido formateando %2d:%02d\n",
tiempo/60, tiempo % 60);
printf (" Volúmen con número de serie %04X-%04X\n",
(int) (s0->NumSerie >> 16), (int) s0->NumSerie);
printf ("%9d ficheros permitidos en el raíz.\n",
s0->FichRaiz);
printf ("%9d unidades de asignación.\n", ua);
printf ("%9d bytes por unidad de asignación.\n",
s0->SectCluster*512);
printf ("%9lu bytes totales en el disco.\n", bt);
printf ("%9lu bytes en sectores defectuosos.\n", bd);
printf ("%9lu bytes disponibles en el disco.\n", bt-bd);
}
else {
printf ("\r Time elapsed in the process %2d:%02d\n",
tiempo/60, tiempo % 60);
printf (" Volume serial number is %04X-%04X\n",
(int) (s0->NumSerie >> 16), (int) s0->NumSerie);
printf ("%9d file capacity of root directory.\n",
s0->FichRaiz);
printf ("%9d total clusters on disk.\n", ua);
printf ("%9d bytes per cluster.\n",
s0->SectCluster*512);
printf ("%9lu total bytes on disk.\n", bt);
printf ("%9lu bytes on bad sectors.\n", bd);
printf ("%9lu bytes available on disk.\n", bt-bd);
}
}
void DiagnosticoError (int codigo)
{
if (sp) {
switch (codigo) {
case 1: printf("\r Formateo interrumpido por el usuario.");
break;
case 2: printf("\r La densidad seleccionada es incorrecta.");
break;
case 3: printf("\r Disquete protegido contra escritura.");
break;
case 6:
case 128: printf("\r Unidad no preparada (¿puerta abierta?).");
break;
default: printf("\r Anomalía general: ¿densidad incorrecta?.");
break;
}
}
else {
switch (codigo) {
case 1: printf("\r Format aborted by user.");
break;
case 2: printf("\r Selected density is incorrect.");
break;
case 3: printf("\r Diskette is write-protected.");
break;
case 6:
case 128: printf("\r Drive not ready (door open?).");
break;
default: printf("\r General failure: incorrect density?.");
break;
}
}
printf(" \n");
}
int MarcaFat (unidad, modosuave, sector0, cil, cab, fat, bytes_mal)
struct boot *sector0;
int unidad, modosuave, cil, cab;
unsigned char far *fat;
long *bytes_mal;
{
unsigned malclus, i, ini, tamsys;
tamsys = sector0->NumFats*sector0->SectFat+(sector0->FichRaiz>>4)+1;
for (i=1; i<=sector0->SectPista; i++) {
ini=(cil*sector0->Caras+cab)*sector0->SectPista+i-1;
if (modosuave)
malclus=biosdsk (2, unidad, cab, cil, i, 1, buffer);
else
malclus=1; /* por defecto marcar la pista entera */
if (malclus) {
if (ini<tamsys) break; /* error en áreas del sistema */
*bytes_mal+=sector0->SectCluster*512L;
ini-=tamsys; ini=ini/sector0->SectCluster+2;
if (ini % 2) { /* posición impar */
fat [ini*3/2] = fat [ini*3/2] & 0x0F | 0x70;
fat [ini*3/2+1] = 0xFF;
}
else { /* posición par */
fat [ini*3/2] = 0xF7;
fat [ini*3/2+1] = fat [ini*3/2+1] & 0xF0 | 0x0F;
}
ini=0x7FFF;
}
}
return (ini>=tamsys);
}
int TipoDrive (int unidad)
{
union REGS r;
r.h.ah=8; r.h.dl=unidad;
int86 (0x13, &r, &r);
return ((unsigned char) r.h.bl);
}
InicializaDisco (unidad, sector0, fat1)
int unidad;
struct boot *sector0;
unsigned char far *fat1;
{
unsigned char far *p;
int sectpista0=sector0->Salto[sector0->OffsetPista0];
p=buffer;
memcpy (p, sector0, 512); /* BOOT físico */
p+=512;
memcpy (p, fat1, sector0->SectFat*512); /* FAT1 (la 2 emulada) */
p+=sector0->SectFat*512;
memcpy (p, sector0, 512); /* BOOT virtual */
p+=512;
memcpy (p, &Boot2mCode, Boot2mLong); /* código SuperBOOT */
biosdsk (0, unidad);
return (biosdsk(3, unidad, 0x80, 0, 1, sectpista0, buffer));
}
void SonidoSube()
{
int frec=50;
SonidoOn();
while (frec<5000) {
Sonido (frec); PicoRetardo(); Sonido (frec+1000); PicoRetardo();
frec+=10;
}
SonidoOff();
}
void SonidoBaja()
{
int frec=6000;
SonidoOn();
while (frec>1050) {
Sonido (frec); PicoRetardo(); Sonido (frec-1000); PicoRetardo();
frec-=10;
}
SonidoOff();
}
void SonidoError()
{
int frec1=50, frec2=6000;
SonidoOn();
while (frec1<5000) {
Sonido (frec1); PicoRetardo(); Sonido (frec1+1000); PicoRetardo();
Sonido (frec2); PicoRetardo(); Sonido (frec2-1000); PicoRetardo();
frec1+=10; frec2-=10;
}
SonidoOff();
}
void SonidoOn()
{
disable(); outportb (0x61, inportb (0x61) | 3); enable();
outportb (0x43, 182); /* preparar canal 2 */
}
void SonidoOff()
{
disable(); outportb (0x61, inportb (0x61) & 0xFC); enable();
}
void Sonido (int frecuencia)
{
unsigned periodo;
periodo=1193180L/frecuencia;
outportb (0x42, periodo & 0xFF); outportb (0x42, periodo >> 8);
}
int EsperarCambioDisco (int unidad)
{
int i;
long hora;
while (bioskey(1)) (void) bioskey(0); /* limpiar buffer teclado */
pokeb(0x40,0x3F, peekb(0x40, 0x3F) & 0xF0); /* "motores apagados" */
do { /* esperar que retiren el disquete */
hora=*cbios+5;
while (*cbios<hora);
outportb (FD_DOR, (1<<(unidad+4)) | unidad | 4+8); /* encender */
i=inportb (FD_DIR); /* leer línea de cambio */
outportb (FD_DOR, unidad | 4+8); /* apagar motor */
i = (i >> 7) | bioskey(1);
} while (!i);
/* intento de bajar la línea de cambio */
while (i && !bioskey(1)) { /* y parpadeo del LED */
hora=*cbios+7;
pokeb (0x40, 0x40, 0xFF); /* para BIOS pelmas no estándar */
outportb (FD_DOR,(1<<(unidad+4)) | unidad | 4+8); /* encender */
posicionar (unidad, 1);
while ((*cbios<hora) && !bioskey(1));
hora+=14;
posicionar (unidad, 0);
i = inportb (FD_DIR) >> 7; /* leer línea de cambio */
outportb (FD_DOR, unidad | 4+8); /* apagar motor */
while ((*cbios<hora) && !bioskey(1));
}
return (bioskey(1)?(bioskey(0) & 0xFF)!=0x1B:1);
}
void posicionar (int unidad, int cilindro) /* mover cabezal */
{
outfdc (0xF); /* comando 'Seek' */
outfdc (unidad); /* byte 1 de dicho comando */
outfdc (cilindro);
EsperarInt(); /* esperar interrupción */
outfdc (8); /* comando 'leer estado de interrupciones' */
(void) infdc(); (void) infdc();
}
void outfdc (unsigned char dato) /* enviar byte al FDC */
{ /* no esperando más de 440 ms */
int i=0, rd;
long t;
do {
i++; t=*cbios;
while ((t==*cbios) && ((rd=inportb(FD_STATUS)>>7)==0));
} while ((i<8) && !rd);
if (rd) outportb (FD_DATA, dato);
}
int infdc (void) /* leer byte del FDC */
{ /* no esperando más de 440 ms */
int i=0, rd;
long t;
do {
i++; t=*cbios;
while ((t==*cbios) && ((rd=inportb(FD_STATUS)>>7)==0));
} while ((i<8) && !rd);
if (rd) return (inportb (FD_DATA)); else return (-1); /* fallo */
}
void EsperarInt (void) /* Esperar interrupción no más de 2 seg. */
{
int i=0;
long t;
do {
i++; t=*cbios;
while ((t==*cbios) && !(*irq6 & 0x80));
} while ((i<37) && !(*irq6 & 0x80));
*irq6=*irq6 & 0x7F;
}
int HablaSp() /* devolver 1 si mensajes en castellano */
{
union REGS r; struct SREGS s;
char info[64];
int i, idioma, spl[]={54, 591, 57, 506, 56, 593, 503, 34, 63, 502,
504, 212, 52, 505, 507, 595, 51, 80, 508, 598, 58, 3, 0};
idioma=0; /* supuesto el inglés */
if (_osmajor>=3) {
r.x.ax=0x3800; s.ds=FP_SEG(info); r.x.dx=FP_OFF(info);
intdosx (&r, &r, &s);
i=0; while (spl[i++]) if (spl[i-1]==r.x.bx) idioma=1;
}
return (idioma);
}